

#ifndef CONFIGURATION_H
#define CONFIGURATION_H

// INCLUDES ********************************************************************

#include "Vector2D.h"

#include "Singleton.h"

#include <UIKit/UIKit.h>

#include <string>

#include <set>

#include <vector>

#include <map>

// FORWARD DECLARATIONS ********************************************************

// *****************************************************************************

//! Configuration
//! 
//! Singleton class storing device information, such as screensize, 
//! the OpenGL version, it's drawing capabilites etc.

// *****************************************************************************

namespace Meteor 
{

    // *************************************************************************

    //! 'abstract' class for entries
    class ConfigurationEntry
    {
        public:
            virtual ~ConfigurationEntry(){};
    };
    
    //! template class for entries, internally used
    template <typename T>
    class ConfigurationEntryImpl : public ConfigurationEntry
    {
        T mValue;
    
        public:
            ConfigurationEntryImpl( T value) : mValue( value){};
        
            ~ConfigurationEntryImpl(){};
        
            const T value(){ return mValue;};
    };
    
    // *************************************************************************
    

    class Configuration : public Singleton<Configuration>
    {
        friend class Singleton<Configuration>;
        
        public:
            template <typename T>
            void SetValueForKey( const std::string& key, const T& value);
        
            template <typename T>
            T ValueForKey( const std::string& key) const;
        
            void RemoveValueForyKey( const std::string& key);
        
        private:
            typedef std::map<std::string, ConfigurationEntry*> containerType;
        
            //! configuration data resides here
            containerType mEntries;
        
            //! prevent copies
            Configuration();
        
            Configuration( const Configuration& rhs);
        
            const Configuration& operator=( const Configuration& rhs);
        
            ~Configuration();
            
            void GetSystemInformation();
        
    }; // end of class Configuration
    
} // end of namespace Meteor

#pragma mark -
#pragma mark Template functions
// -----------------------------------------------------------------------------

template <typename T>
T Meteor::Configuration::ValueForKey( const std::string& key) const
{
    const containerType::const_iterator entry = mEntries.find( key);
    
    if ( entry == mEntries.end())
    {
        Logger::DebugLog( "Configuration::ValueForKey - unknown key '%s' queried.",
                          key.c_str());
        
        return 0;
    }
    
    ConfigurationEntryImpl<T>* result = reinterpret_cast<ConfigurationEntryImpl<T>*>( ( *entry).second);
    
    return result->value();
}

// -----------------------------------------------------------------------------

template <typename T>
void Meteor::Configuration::SetValueForKey( const std::string& key, const T& value)
{
    ConfigurationEntryImpl<T>* newEntry = new ConfigurationEntryImpl<T>( value);
    
    containerType::iterator oldValue = mEntries.find( key);
    
    if ( oldValue != mEntries.end())
    {
        delete ( *oldValue).second;
    
        mEntries.erase( oldValue);
    }
    
    mEntries.insert( std::pair<std::string, ConfigurationEntry*> ( key, newEntry));
}


#endif
